package java2020spring;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JTextField;

public class CalculatorListener implements ActionListener {
	private JTextField ctf;
	private StringBuffer sb = new StringBuffer();
	public CalculatorListener(JTextField ctf) {
		this.ctf = ctf;
		ctf.addKeyListener(new KeyAdapter() {//键盘事件
            public void keyPressed(KeyEvent e) {
            	if(e.getKeyChar()==8) {//删除键，清空键盘输入的数据
            		sb.setLength(0);
    			    ctf.setText("0");
            	}
				switch(e.getKeyChar()) {
				case'0':
				case'1':
				case'2':
				case'3':
				case'4':
				case'5':
				case'6':
				case'7':
				case'8':
				case'9':
				case '.':
				case'+':
				case'-':
				case'x':
				case'%':
                    sb.append(e.getKeyChar());
                    ctf.setText(sb.toString().trim());
                    break;
				case'*'://将键盘输入的/与*转换为÷和x
					sb.append("x");
                    ctf.setText(sb.toString().trim());
                    break;
				case'^':
					sb.append('^');
					ctf.setText(sb.toString().trim());
					String a = ctf.getText();
					if (a.contains("^")) {
						String[] string = a.split("\\^");
						String  A= string[0];
						double result = Double.valueOf(A)*Double.valueOf(A);
						ctf.setText(String.valueOf(result));
					}
					break;
				case'/':
					sb.append("÷");
                    ctf.setText(sb.toString().trim());
                    break;
				case '=':
					String content = ctf.getText();
					NCStack ncStack = new NCStack(14);
					NCStack operationStack = new NCStack(14);
				        int i = 0;
				        int one = 0;//数字
				        int two = 0;//数字
				        int operator = 0;//运算符
				        int result = 0;
				        char nc = ' ';
				        String Num = "";
				        while (true) {
				        	nc = content.substring(i, i + 1).charAt(0);//chartAt转换字符
				            if (operationStack.isOperator(nc)) {
				                if (!operationStack.isEmpty()) {
				                    if (operationStack.priority(nc) <= operationStack.priority(operationStack.peek())) {//字符、运算符优先级比较
				                    	one = ncStack.pop();
				                    	two = ncStack.pop();
				                    	operator = operationStack.pop();
				                    	result = ncStack.operation(one, two, operator);
				                        ncStack.push(result);
				                        operationStack.push(nc);
				                    } 
				                    else {
				                    	operationStack.push(nc);
				                    }
				                } 
				                else {
				                	operationStack.push(nc);
				                }
				            } 
				            else {
				            	Num += nc;
				                if(i==content.length()-1){
				                	ncStack.push(Integer.parseInt(Num));
				                } 
				                else if (operationStack.isOperator(content.substring(i + 1, i + 2).charAt(0))) {//如果后一位是运算符，将Num转换为int,一并入栈
				                    	ncStack.push(Integer.parseInt(Num));
				                    	Num = "";
				                }
				            }
				            i++;
				            if (i >= content.length()) {
				                break;
				            }
				        }
				        while (true) {
				            if (operationStack.isEmpty()) {
				                break;
				            }
				            one = ncStack.pop();
				            two = ncStack.pop();
				            operator = operationStack.pop();
				            result = ncStack.operation(one, two, operator);
				            ncStack.push(result);
				        }
                }
			}
		});
	}
	public void actionPerformed(ActionEvent e) {
		switch (e.getActionCommand()) {
		case "1":
		case "2":
		case "3":
		case "4":
		case "5":
		case "6":
		case "7":
		case "8":
		case "9":
		case "0":
		case ".":
		case "+":
		case "-":
		case "x":
		case "%":
		case "÷":
			sb.append(e.getActionCommand());
			ctf.setText(sb.toString().trim());//toString().trim():获得对象的字段的值，然后转成string类型，并且去掉前后空白
			break;
		case "√":
			sb.append('√');
			ctf.setText(sb.toString().trim());
			String c = ctf.getText();
			if (c.contains("√")) {
				String[] string = c.split("\\√");
				String  A= string[0];
				double result = Math.sqrt(Double.valueOf(A));
				ctf.setText(String.valueOf(result));
			}
            break;
		case "e^a":
			sb.append('@');
			ctf.setText(sb.toString().trim());
			String d = ctf.getText();
			if (d.contains("@")) {
				String[] string = d.split("\\@");
				String  A= string[0];
				double result = Math.exp(Double.valueOf(A));
				ctf.setText(String.valueOf(result));
			}
            break;
		case "1/x":
			sb.append('#');
			ctf.setText(sb.toString().trim());
			String f = ctf.getText();
			if (f.contains("#")) {
				String[] string = f.split("\\#");
				String  A= string[0];
				double result = 1/Double.valueOf(A);
				ctf.setText(String.valueOf(result));
			}
            break;
		case "lnx":
			sb.append('$');
			ctf.setText(sb.toString().trim());
			String g = ctf.getText();
			if (g.contains("$")) {
				String[] string = g.split("\\$");
				String  A= string[0];
				double result = Math.log(Double.valueOf(A));
				ctf.setText(String.valueOf(result));
			}
            break;
		case "lgx":
			sb.append('&');
			ctf.setText(sb.toString().trim());
			String h = ctf.getText();
			if (h.contains("&")) {
				String[] string = h.split("\\&");
				String  A= string[0];
				double result = Math.log10(Double.valueOf(A));
				ctf.setText(String.valueOf(result));
			}
            break;
		case "cbrt":
			sb.append('~');
			ctf.setText(sb.toString().trim());
			String k = ctf.getText();
			if (k.contains("~")) {
				String[] string = k.split("\\~");
				String  A= string[0];
				double result = Math.cbrt(Double.valueOf(A));
				ctf.setText(String.valueOf(result));
			}
            break;
		case "x²":
			sb.append('^');
			ctf.setText(sb.toString().trim());
			String a = ctf.getText();
			if (a.contains("^")) {
				String[] string = a.split("\\^");
				String  A= string[0];
				double result = Math.pow(Double.valueOf(A),2);
				ctf.setText(String.valueOf(result));
			}
            break;
		case "x³":
			sb.append('*');
			ctf.setText(sb.toString().trim());
			String b = ctf.getText();
			if (b.contains("*")) {
				String[] string = b.split("\\*");
				String  A= string[0];
				double result = Math.pow(Double.valueOf(A),3);
				ctf.setText(String.valueOf(result));
			}
			break;
		case "AC":
			sb.setLength(0);
			ctf.setText("0");
			break;
		case "+/-":
			if (ctf.getText().startsWith("-")) {
				ctf.setText(ctf.getText().replace("-", ""));
			} 
			else {
				ctf.setText("-" + ctf.getText());
			}
			break;
		case "=":
			String content = ctf.getText();
			NCStack ncStack = new NCStack(14);
			NCStack operationStack = new NCStack(14);
		        int i = 0;
		        int one = 0;
		        int two = 0;
		        int operator = 0;
		        int result = 0;
		        char nc = ' ';
		        String Num = "";
		        while (true) {
		        	nc = content.substring(i, i + 1).charAt(0);//chartAt转换字符
		            if (operationStack.isOperator(nc)) {
		                if (!operationStack.isEmpty()) {
		                    if (operationStack.priority(nc) <= operationStack.priority(operationStack.peek())) {//字符、运算符优先级比较
		                    	one = ncStack.pop();
		                    	two = ncStack.pop();
		                    	operator = operationStack.pop();
		                    	result = ncStack.operation(one, two, operator);
		                        ncStack.push(result);
		                        operationStack.push(nc);
		                    } 
		                    else {
		                    	operationStack.push(nc);
		                    }
		                } 
		                else {
		                	operationStack.push(nc);
		                }
		            } 
		            else {
		            	Num += nc;
		                if(i==content.length()-1){
		                	ncStack.push(Integer.parseInt(Num));
		                } 
		                else if (operationStack.isOperator(content.substring(i + 1, i + 2).charAt(0))) {////如果后一位是运算符，将Num转换为int,一并入栈
		                    	ncStack.push(Integer.parseInt(Num));
		                    	Num = "";
		                }
		            }
		            i++;
		            if (i >= content.length()) {
		                break;
		            }
		        }
		        while (true) {
		            if (operationStack.isEmpty()) {
		                break;
		            }
		            one = ncStack.pop();
		            two = ncStack.pop();
		            operator = operationStack.pop();
		            result = ncStack.operation(one, two, operator);
		            ncStack.push(result);
		        }
		    }
		}
		class NCStack {
		    private int maxSize;
		    private int stack[];
		    private int top;
		    public NCStack(int s) {
		        maxSize = s;
		        stack = new int[maxSize];
		        top = -1;
		    }
		    public int peek() {
		        return stack[top];
		    }
		    public boolean isFull() {
		        return top == maxSize - 1;
		    }
		    public boolean isEmpty() {
		        return top == -1;
		    }
		    public void push(int n) {
		        stack[++top] = n;
		    }
		    public int pop() {
		        return stack[top--];
		    }
		    public int priority(int operator) {//优先级
		    	if(operator =='²')
		    		return 4;
		        if (operator == 'x')
		            return 1;
		        if(operator == '%')
		        	return 3;
		        if(operator == '÷')
		        	return 2;
		        else if (operator == '+' || operator == '-') 
		            return 0;
		        else 
		            return -1;
		    }
		    public boolean isOperator(char operator) {
		        return operator == '+' || operator == '-' || operator == 'x' || operator == '÷'|| operator =='%'||operator =='²';
		    }
		    public int operation(int one, int two, int operator) {//运算
		        int result = 0;
		        if(operator == '%')
		        	result = two % one;
		        if(operator == '÷')
		        	result = two / one;
		        if(operator == 'x')
		        	result = two * one;
		        if(operator == '-')
		        	result = two - one;
		        if(operator == '+')
		        	result = two + one;
		        ctf.setText(""+result);
		        return result;
		    }
		}
}
